﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing.Printing;
using OwnZTec.LojaDelivery.Data;

namespace OwnZTec.LojaDelivery.Impressao
{
    public class Impressao
    {

        private static mdlDbLojaDeliveryContainer _db;

        internal static mdlDbLojaDeliveryContainer Db
        {
            get { return _db ?? (_db = new mdlDbLojaDeliveryContainer()); }
        }

        private StringBuilder sb;

        public void ImprimeDesperdicio(StringBuilder sb)
        {
            sb = insereRodapeFinal(sb);
            PrintDialog pd = new PrintDialog();
            pd.PrinterSettings = new PrinterSettings();
            RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, sb.ToString());
        }

        private StringBuilder insereRodapeFinal(StringBuilder sb)
        {
            sb.AppendLine("");
            sb.AppendLine("==== Emitido em " + DateTime.Now.ToString() + " =====");
            sb.AppendLine("================== FIM ==================");
            //Inserindo espaços para cortar
            for (int i = 0; i <= 7; i++)
            {
                sb.AppendLine("");
            }
            return sb;
        }

        /// <summary>
        /// Método que insere o rodapé no final da impressão
        /// </summary>
        /// <param name="sb">StringBuilder para ser adicionado o rodapé </param>
        /// <returns>Retorna StringBuilder com o radapé adicionado</returns>
        private StringBuilder rodapeTotal(StringBuilder sb)
        {
            sb.AppendLine("================== FIM ==================");
            //Inserindo espaços para cortar
            for (int i = 0; i <= 7; i++)
            {
                sb.AppendLine("");
            }
            return sb;
        }

        /// <summary>
        /// Método que insere o cabeçalho nas comandas
        /// </summary>
        /// <param name="sb">StringBuilder para ser adicionado o cabeçalho</param>
        /// <returns>Retorna StringBuilder com o cabeçalho adicionado</returns>
        private StringBuilder cabecalhoComanda(StringBuilder sb)
        {
            sb.AppendLine("CELIA SALGADOS - (19)3254-1222-3252-6926");
            sb.AppendLine("Emitido em " + DateTime.Now.ToString());
            sb.AppendLine("5Power Sistemas");
            sb.AppendLine("PEDIDO DE COMPRA - ( SEM VALOR FISCAL )");
            sb.AppendLine("=========================================");
            return sb;
        }

        private StringBuilder insereProdutos(StringBuilder sb)
        {
            sb.AppendLine("Cod    Descricao do Salgado");
            sb.AppendLine("          Qtde     Unit R$       Total R$");
            sb.AppendLine("=========================================");

            //Loping para popular os valores
            sb.AppendLine("0004    ESFIHA DE CARNE");
            sb.AppendLine("           3 x      1,25       =    3,75");
            sb.AppendLine("0005    ESFIHA DE FRANGO");
            sb.AppendLine("           2 x      1,25       =    2,50");
            sb.AppendLine("0007    CROISSANT PRES/QUEIJO");
            sb.AppendLine("           2 x      1,25       =    2,50");
            sb.AppendLine("0018    CALABRESA");
            sb.AppendLine("           3 x      1,25       =    3,75");
            sb.AppendLine("0019    HAMBURGUER");
            sb.AppendLine("           2 x      1,25       =    2,50");
            sb.AppendLine("0040    COXINHA");
            sb.AppendLine("           3 x      1,20       =    3,60");
            sb.AppendLine("=========================================");

            return sb;
        }

        private StringBuilder insereRodapeComanda(StringBuilder sb)
        {
            sb.AppendLine("");
            sb.AppendLine("Validade:");
            sb.AppendLine("- Consumo IMEDIATO (quando aquecido)");
            sb.AppendLine("- 2 (dois) dias se mantido sob");
            sb.AppendLine("  refrigeracao imediatamente apos");
            sb.AppendLine("  o recebimento");
            sb.AppendLine("- 60 (sessenta) dias se congelado");
            sb.AppendLine("  IMEDIATAMENTE apos o recebimento");

            sb = rodapeTotal(sb);
            return sb;
        }

        public void ImprimeComanda()
        {
            sb = new StringBuilder();
            sb = cabecalhoComanda(sb);
            
            sb.AppendLine("Comanda : 247500");
            sb.AppendLine("Cliente : EVANDRO MARQUES 3 RIOS");
            sb.AppendLine("Endereco: R. MARQUES DE 3 RIOS");
            sb.AppendLine("Data da Venda: " + DateTime.Now.ToShortDateString());
            sb.AppendLine("=========================================");
            sb.AppendLine("Motorista: NOME DO MOTORISTA");
            sb.AppendLine("=========================================");
            

            
            sb.AppendLine("Qtde Total: 15                 =   18,60");
            sb.AppendLine("Desconto da Nota : R$ 0,00");
            sb.AppendLine("Acrescimo da Nota: R$ 0,00");
            sb.AppendLine("");
            sb.AppendLine("****** Total da Comanda: R$ 18,60 ******");

            sb = insereRodapeComanda(sb);

            PrintDialog pd = new PrintDialog();
            pd.PrinterSettings = new PrinterSettings();
            RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, sb.ToString());
        }
    }

    /// <summary>
    /// Classe utilizada para impressão
    /// </summary>
    public class RawPrinterHelper
    {
        // Structure and API declarions:
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public class DOCINFOA
        {
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDocName;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pOutputFile;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDataType;
        }
        [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool ClosePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

        [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

        // SendBytesToPrinter()
        // When the function is given a printer name and an unmanaged array
        // of bytes, the function sends those bytes to the print queue.
        // Returns true on success, false on failure.
        public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
        {
            Int32 dwError = 0, dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            DOCINFOA di = new DOCINFOA();
            bool bSuccess = false; // Assume failure unless you specifically succeed.

            di.pDocName = "My C#.NET RAW Document";
            di.pDataType = "RAW";

            // Open the printer.
            if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
            {
                // Start a document.
                if (StartDocPrinter(hPrinter, 1, di))
                {
                    // Start a page.
                    if (StartPagePrinter(hPrinter))
                    {
                        // Write your bytes.
                        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                        EndPagePrinter(hPrinter);
                    }
                    EndDocPrinter(hPrinter);
                }
                ClosePrinter(hPrinter);
            }
            // If you did not succeed, GetLastError may give more information
            // about why not.
            if (bSuccess == false)
            {
                dwError = Marshal.GetLastWin32Error();
            }
            return bSuccess;
        }

        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            IntPtr pBytes;
            Int32 dwCount;
            // How many characters are in the string?
            dwCount = szString.Length;
            // Assume that the printer is expecting ANSI text, and then convert
            // the string to ANSI text.
            pBytes = Marshal.StringToCoTaskMemAnsi(szString);
            // Send the converted ANSI string to the printer.
            SendBytesToPrinter(szPrinterName, pBytes, dwCount);
            Marshal.FreeCoTaskMem(pBytes);
            return true;
        }
    }
}
